package itsm.isperp.workflow.utils;

import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import groovy.util.ResourceException;
import groovy.util.ScriptException;
import itsm.isperp.framework.core.context.ContextHolder;
import itsm.isperp.framework.data.dialect.DialectFactory;
import itsm.isperp.framework.domain.IUser;
import itsm.isperp.module.entity.db.DbEntity;
import itsm.isperp.module.service.app.UserAccountService;
import itsm.isperp.module.service.bpm.BpmProcessSettingService;
import itsm.isperp.module.service.db.DbEntityService;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.VariableScope;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;

/**
 * 
 * 
 * 
 * @author lizx
 * @date 2013-9-17
 * @since 1.0
 * 
 */
public final class BpmScriptUtils {

	protected static Logger logger = LoggerFactory
			.getLogger(BpmScriptUtils.class);

	public static void startEventScript(VariableScope delegateTask,
			DelegateExecution delegateExecution, String scriptType,
			String defId, String nodeId) throws ResourceException,
			ScriptException, SQLException {

		JdbcTemplate jdbcTemplate = ContextHolder.getSpringBean("jdbcTemplate");
		String businessKey = delegateExecution.getProcessBusinessKey();

		Map<String, Object> vars = getVariables(delegateTask, defId,
				jdbcTemplate, businessKey);

		exeEventScript(delegateTask, delegateExecution, scriptType, defId,
				nodeId, businessKey, jdbcTemplate, vars);

		// String sql =
		// "SELECT c.table_name FROM bpm_node_setting a INNER JOIN "
		// + " bpm_process_setting  b ON a.bpm_process_setting_id=b.id "
		// + " INNER JOIN db_entity c ON b.db_entity_id=c.id "
		// + "WHERE a.act_node_id='" + nodeId + "' "
		// + DialectFactory.getDialect().getLimitString(0, 1);
		//
		// try {
		//
		// String tableName = jdbcTemplate.queryForObject(sql, String.class);
		// @SuppressWarnings("unchecked")
		// String projectId = (String) ((Map<String, Object>) vars
		// .get("bpmBusinessModel")).get("project_id");
		//
		// SlmServiceAgreementService.insertSlmBusObject(businessKey,
		// projectId, tableName, jdbcTemplate);
		//
		// } catch (Exception e) {
		// logger.error(e.getMessage(), e);
		// }

	}

	public static void endEventScript(VariableScope delegateTask,
			DelegateExecution delegateExecution, String scriptType,
			String defId, String nodeId) throws ResourceException,
			ScriptException, SQLException {

		JdbcTemplate jdbcTemplate = ContextHolder.getSpringBean("jdbcTemplate");
		String businessKey = delegateExecution.getProcessBusinessKey();

		Map<String, Object> vars = getVariables(delegateTask, defId,
				jdbcTemplate, businessKey);

		exeEventScript(delegateTask, delegateExecution, scriptType, defId,
				nodeId, businessKey, jdbcTemplate, vars);

	}

	/**
	 * 
	 * @param delegateTask
	 * @param scriptType
	 * @param defId
	 * @param nodeId
	 * @throws ResourceException
	 * @throws ScriptException
	 * @throws SQLException
	 */
	public static void exeEventScript(VariableScope delegateTask,
			DelegateExecution delegateExecution, String scriptType,
			String defId, String nodeId) throws ResourceException,
			ScriptException, SQLException {
		JdbcTemplate jdbcTemplate = ContextHolder.getSpringBean("jdbcTemplate");
		String businessKey = delegateExecution.getProcessBusinessKey();

		exeEventScript(delegateTask, delegateExecution, scriptType, defId,
				nodeId, businessKey, jdbcTemplate, null);
	}

	public static void exeEventScript(VariableScope delegateTask,
			DelegateExecution delegateExecution, String scriptType,
			String defId, String nodeId, String businessKey,
			JdbcTemplate jdbcTemplate, Map<String, Object> vars)
			throws ResourceException, ScriptException, SQLException {

		Map<String, Object> model = jdbcTemplate
				.queryForMap(DialectFactory
						.getDialect()
						.getLimitString(
								"SELECT "
										+ scriptType
										+ " AS script_content  FROM bpm_node_setting WHERE act_node_id='"
										+ nodeId + "'  "));
		if (model == null || model.get("script_content") == null)
			return;
		String script = model.get("script_content").toString();
		if (StringUtils.isEmpty(script)) {
			return;
		} else {
			if (vars == null) {
				vars = getVariables(delegateTask, defId, jdbcTemplate,
						businessKey);
			}

			Binding bd = new Binding(vars);
			GroovyShell shell = new GroovyShell(bd);
			shell.evaluate(script);

			return;
		}
	}

	private static Map<String, Object> getVariables(VariableScope delegateTask,
			String defId, JdbcTemplate jdbcTemplate, String businessKey)
			throws SQLException {
		Map<String, Object> vars = delegateTask.getVariables();
		vars.put("task", delegateTask);
		vars.put("dao", jdbcTemplate);
		vars.put("businessKey", businessKey);

		Object bpmCurrentUser = vars.get("bpmCurrentUser");
		if (bpmCurrentUser != null && vars.get("bpmCurrentUserBean") != null) {

			UserAccountService userAccountService = ContextHolder
					.getSpringBean("userAccountService");
			IUser u = userAccountService.findByUsername(bpmCurrentUser
					.toString());

			vars.put("bpmCurrentUserBean", u);
		} else {
			vars.put("bpmCurrentUserBean", vars.get("bpmCurrentUserBean"));
		}

		if (vars.containsKey("bpmBusinessModel")) {

			vars.put("bpmBusinessModel", vars.get("bpmBusinessModel"));

		} else {
			DbEntityService dbEntityService = ContextHolder
					.getSpringBean(DbEntityService.class);
			BpmProcessSettingService bpmProcessSettingService = ContextHolder
					.getSpringBean(BpmProcessSettingService.class);
			DbEntity entity = bpmProcessSettingService.findDbEntityByKey(defId
					.split(":")[0]);
			Map<String, Object> entityMap = dbEntityService
					.getDataFromDbEntity(entity, businessKey);
			vars.put("bpmBusinessModel", entityMap);

		}

		return vars;
	}

	public static void transferAssigneeScript(String assignee,
			String processId, String taskId, String nodeId, String businessKey)
			throws ResourceException, ScriptException, SQLException {

		JdbcTemplate jdbcTemplate = ContextHolder.getSpringBean("jdbcTemplate");

		Map<String, Object> model = jdbcTemplate
				.queryForMap(DialectFactory
						.getDialect()
						.getLimitString(
								"SELECT transfer_script_content   AS script_content  FROM bpm_node_setting WHERE act_node_id='"
										+ nodeId + "'  "));
		if (model == null || model.get("script_content") == null)
			return;
		String script = model.get("script_content").toString();
		if (StringUtils.isEmpty(script)) {
			return;
		} else {
			Map<String, Object> vars = new HashMap<>();
			vars.put("processId", processId);
			vars.put("businessKey", businessKey);
			vars.put("assignee", assignee);
			vars.put("dao", jdbcTemplate);
			Binding bd = new Binding(vars);
			GroovyShell shell = new GroovyShell(bd);
			shell.evaluate(script);

			return;
		}

	}
}
